#pragma once

#include "noncopyable.h"
#include "InetAddress.h"
#include "Callback.h"
#include "Timestamp.h"
#include "Buffer.h"

#include <memory>
#include <string>
#include <atomic>

class Channel;
class EventLoop;
class Socket;


/*
用于允许对象自己获取一个指向自身的 std::shared_ptr
当类继承自 std::enable_shared_from_this<T> 后
成员函数可以通过 shared_from_this() 方法返回一个 shared_ptr<T> 实例
*/

class TcpConnection:noncopyable,public std::enable_shared_from_this<TcpConnection>
{
public:
    TcpConnection(EventLoop* loop,const std::string& name,int sockfd,const InetAddress& localAddr,const InetAddress& peerAddr);
    ~TcpConnection();

    EventLoop* getLoop() const {return loop_;}
    const std::string& name() const {return name_;}
    const InetAddress& localAddress() const {return localAddr_;}
    const InetAddress& peerAddress() const {return peerAddr_;}

    bool connected() const {return state_==kConnected;}

    
    void send(const std::string& buf);
    void shutdown();

    void setConnectionCallback(const ConnectionCallback& cb) {connectionCallback_ = cb; }
    void setCloseCallback(const CloseCallback& cb) {closeCallback_=cb;}
    void setMessageCallback(const MessageCallback& cb) {messageCallback_ = cb; }
    void setWriteCompleteCallback(const WriteCompleteCallback& cb) {writeCompleteCallback_ = cb; }
    
    void connectEstablished();
    void connectDestroyed();

private:
    enum State{kDisconnected,kConnecting,kConnected,kDisconnecting};

    static EventLoop* CheckLoopNotNull(EventLoop* loop);
    
    void setState(State state) {state_=state;}

    void handleRead(Timestamp recvTime);
    void handleWrite();
    void handleClose();
    void handleError();

    void sendInLoop(const void* message,size_t len);
    void shutdownInLoop();

    EventLoop* loop_; // 此处不是mainLoop TcpConnection都是在subLoop里面管理的
    const std::string name_;
    std::atomic_int state_;
    bool reading_;

    std::unique_ptr<Socket> socket_;
    std::unique_ptr<Channel> channel_;

    const InetAddress localAddr_;
    const InetAddress peerAddr_;

    
    ConnectionCallback connectionCallback_; // 有新连接时的回调
    MessageCallback messageCallback_; // 有读写消息时的回调
    WriteCompleteCallback writeCompleteCallback_; // 消息发送完成以后的回调
    CloseCallback closeCallback_;

    Buffer inputBuffer_;
    Buffer outputBuffer_;
};